"""
    canon.py

    PURPOSE
    Keeps a rolling backup of Hailbot's Twitter faves. Saves two different
    files:

    1. A list of fave digests (see below)
    2. A list of twitter ids (which is pushed to Google Code)

    USAGE
    Command Line:
    python hailbot/twitter/canon.py usage

    NOTES
    Saves faves as a list of digests or tuples:
    [(tweet_id, user_id, screen_name, tweet)]

    Twitter API authentication settings should be imported from a module with
    following settings:

    screen_name     = 'hailbot666'
    consumer_key    = 'my-consumer-key'
    consumer_secret = 'my-consumer-secret'
    access_key      = 'my-access-key'
    access_secret   = 'my-access-secret'

    DEPENDENCIES
    Python 2.5+
    Tweepy python API library

    REFERENCES

    LICENSE
    hailbot666@gmail.com
    some rights reserved, 2011
"""
#
# IMPORTS
#
# Python Imports
import sys, os, pdb, logging
from os.path import (abspath, dirname, join as pathjoin, exists)
from datetime import(datetime, date, timedelta)
from random import (choice, sample, randint)
from pprint import (pprint, pformat)

# Extend sys.path (where config file is located)
PROJECT_PATH = abspath(pathjoin(dirname(__file__), '../..'))
HG_PATH = pathjoin(PROJECT_PATH, 'hailbot')
sys.path.append(PROJECT_PATH)
sys.path.append(HG_PATH)
sys.path.append(pathjoin(HG_PATH, 'external'))

# Impot Tweepy
from tweepy import tweepybot

# Import Config File
from config import hailbot



#
# MODULE ATTRIBUTES
#
# Exception Classes
class NullException(Exception): pass



#
# HAILBOT HIMSELF
#
class Hailbot(tweepybot.Bot):
    consumer_key        = hailbot.consumer_key
    consumer_secret     = hailbot.consumer_secret
    access_key          = hailbot.access_key
    access_secret       = hailbot.access_secret
    fave_count_limit    = 666


#
# COMMANDS
#
def archive():
    """loads the existing hailbot_archive module and updates it with digests
    of all current favorites. A digest is tuple which includes:
        [0] : status id
        [1] : user id
        [2] : user screen name
        [3] : status text
    """
    # import current canon backup
    from data.hailbot_canon_digest import faves as canon_faves
    print 'loaded %s favorites from existing canon' % (len(canon_faves))

    # get active favorites from twitter (0 limit means get them all)
    hailbot = Hailbot(read_only=True)
    active_faves = []
    favorites = hailbot.get_favorites(limit=0)
    for status in favorites:
        digest = (status.id, status.user.id, status.user.screen_name, status.text)
        active_faves.append(digest)
    print 'downloaded %s favorites from twitter' % (len(active_faves))

    # join lists to build new list
    fave_dict = {}
    for f in canon_faves + active_faves:
        fave_dict[f[0]] = f
    new_list = fave_dict.values()

    # before saving verify that new list larger than old list
    old_count = len(canon_faves)
    new_count = len(new_list)

    if new_count < old_count:
        raise Exception('new list (%s) is shorter than old list (%s)' % (
            new_count, old_count))
    elif new_count == old_count:
        print 'no new faves -- count still at %s' % (old_count)
    else:
        print 'new list of faves: %s' % (new_count)

    # save digest canon
    file_path = pathjoin(HG_PATH, 'data/hailbot_canon_digest.py')
    saved_file = save_canon_module(new_list, file_path)
    print 'digest canon saved to: %s' % (file_path)

    # save id canon
    id_list = [t[0] for t in new_list]
    file_path = pathjoin(HG_PATH, 'data/hailbot_canon_id.py')
    saved_file = save_id_module(id_list, file_path)
    print 'id canon saved to: %s' % (file_path)

    return



def interact():
    # import current canon backup
    from data.hailbot_canon_digest import faves
    print 'loaded %s favorites from existing canon' % (len(faves))

    # index
    users = {}
    for f in faves:
        tid, uid, name, tweet = f
        if name in users:
            users[name].append(tweet)
        else:
            users[name] = [tweet]

    top = []
    for name in users:
        top.append((name, len(users[name])))
    top = sorted(top, key=lambda tup: tup[1], reverse=True)

    rank = {}
    r = 0   # track rank
    c = 0   # to count ties
    for n in range(len(top)):
        name, count = top[n]
        if count != c:
            r = n + 1
            c = count
        rank[name] = (r, count)

    # load hailbot
    hailbot = Hailbot(read_only=True)

    # interact
    print 'faves are loaded in vars [faves], {users}, [top], {rank}. Or dir(hailbot)'
    print 'You may interact now'
    pdb.set_trace()



def test():
    hailbot = Hailbot(read_only=True)
    print 'Hello, my name is %s' % (hailbot.screen_name)





#
# support functions
#
def save_canon_module(faves, file_path):
    # sort by id
    faves = sorted(faves, key=lambda tup: tup[0], reverse=False)
    count = len(faves)
    now = datetime.now()
    today = str(date.today()).replace('-', '')

    # get oldest and newest
    hailbot = Hailbot(read_only=True)
    oldest = hailbot.get_status(faves[0][0])
    newest = hailbot.get_status(faves[-1][0])

    # format header
    header = """\
# backup of @hailbot666 favorites
# created: %s
# total tweets [n]: %s
# oldest: %s
# newest: %s
# ordered oldest [0] to newest [n]
""" % (now, count, oldest.created_at, newest.created_at)

    # format file
    output = """\
%s

faves = %s
""" % (header, pformat(faves))

    # save
    fh = open(file_path, 'w')
    fh.write(output)
    fh.close()
    return file_path


def save_id_module(id_list, file_path):
    # sort by id
    id_list.sort(reverse=False)
    count = len(id_list)
    now = datetime.now()
    today = str(date.today()).replace('-', '')

    # get oldest and newest
    hailbot = Hailbot(read_only=True)
    oldest = hailbot.get_status(id_list[0])
    newest = hailbot.get_status(id_list[-1])

    # format header
    header = """\
# backup of @hailbot666 favorites
# created: %s
# total tweets [n]: %s
# oldest: %s
# newest: %s
# ordered oldest [0] to newest [n]
""" % (now, count, oldest.created_at, newest.created_at)

    # format file
    output = """\
%s

fave_ids = %s
""" % (header, pformat(id_list))

    # save
    fh = open(file_path, 'w')
    fh.write(output)
    fh.close()
    return file_path



#
# Main
#
def main():
    command = (len(sys.argv) < 2) and 'usage' or sys.argv[1]

    if command == 'archive':
        archive()

    elif command == 'interact':
        interact()

    elif command == 'test':
        test()

    else:
        usage()


def usage():
    print """
    USAGE:
    python %s [archive|interact|test]


""" % (sys.argv[0])


if __name__ == "__main__":
    main()
